package com.jiangyg.mall.redis.support;

import com.jiangyg.mall.core.support.cache.CacheAdapter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 类描述：Redis缓存适配器
 *
 * @author jiangyg
 * @version 2.0
 * @date 2019-10-13
 */
@Slf4j
@SuppressWarnings("unchecked")
public class RedisCacheAdapter implements CacheAdapter {

    /**
     * Redis缓存操作模板
     */
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public <T extends Serializable> void put(String key, T value) {
        getRedisTemplate().opsForValue().set(key, value);
    }

    @Override
    public <T extends Serializable> void put(String key, T value, long timeout) {
        getRedisTemplate().opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
    }

    @Override
    public <T extends Serializable> void hput(String key, String hashKey, T value) {
        getRedisTemplate().opsForHash().put(key, hashKey, value);
    }

    @Override
    public <T extends Serializable> void hput(String key, String hashKey, T value, long timeout) {
        getRedisTemplate().opsForHash().put(key, hashKey, value);
        getRedisTemplate().expire(key, timeout, TimeUnit.SECONDS);
    }

    @Override
    public <T extends Serializable> void hputAll(String key, Map<String, T> hashMap) {
        getRedisTemplate().opsForHash().putAll(key, hashMap);
    }

    @Override
    public <T extends Serializable> void hputAll(String key, Map<String, T> hashMap, long timeout) {
        getRedisTemplate().opsForHash().putAll(key, hashMap);
        getRedisTemplate().expire(key, timeout, TimeUnit.SECONDS);
    }

    @Override
    public <T extends Serializable> void sput(String key, Collection<T> values, long timeout) {
        getRedisTemplate().opsForSet().add(key, values.toArray(new Object[0]));
        getRedisTemplate().expire(key, timeout, TimeUnit.SECONDS);
    }

    @Override
    public <T extends Serializable> void putIfAbsent(String key, T value) {
        getRedisTemplate().opsForValue().setIfAbsent(key, value);
    }

    @Override
    public <T extends Serializable> void putIfAbsent(String key, T value, long timeout) {
        getRedisTemplate().opsForValue().setIfAbsent(key, value, timeout, TimeUnit.SECONDS);
    }

    @Override
    public <T extends Serializable> void hputIfAbsent(String key, String hashKey, T value) {
        getRedisTemplate().opsForHash().putIfAbsent(key, hashKey, value);
    }


    @Override
    public <T extends Serializable> T get(String key) {
        return (T) getRedisTemplate().opsForValue().get(key);
    }

    @Override
    public <T extends Serializable> T hget(String key, String hashKey) {
        return (T) getRedisTemplate().opsForHash().get(key, hashKey);
    }

    @Override
    public boolean containsKey(String key) {
        final Boolean b = getRedisTemplate().hasKey(key);
        return b != null && b;
    }

    @Override
    public boolean hcontainsKey(String key, String hashKey) {
        return getRedisTemplate().opsForHash().hasKey(key, hashKey);
    }

    @Override
    public <T extends Serializable> boolean scontains(String key, T value) {
        return getRedisTemplate().opsForSet().isMember(key, value);
    }

    @Override
    public void remove(String key) {
        getRedisTemplate().delete(key);
    }

    @Override
    public void hremove(String key, String hashKey) {
        getRedisTemplate().opsForHash().delete(key, hashKey);
    }

    @Override
    public Long increment(String key, Long num) {
        return getRedisTemplate().opsForValue().increment(key, num);
    }

    @Override
    public Long hincrement(String key, String hashKey, Long num) {
        return getRedisTemplate().opsForHash().increment(key, hashKey, num);
    }

    @Override
    public List<String> getKeys() {
        Set<String> sets = getRedisTemplate().keys("*");
        if (sets == null) {
            return new ArrayList<>();
        }
        List<String> list = new ArrayList<>(sets.size());
        list.addAll(sets);
        return list;
    }

    @Override
    public String type() {
        return "Redis";
    }

    private RedisTemplate<String, Object> getRedisTemplate() {
        return redisTemplate;
    }

    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

}
